#include "ringbuffer.h"
#include "log.h"
#include <stdlib.h>
RingBuffer* new_ring_buffer(int size,WriteMode mode){
    RingBuffer* buf = (RingBuffer*)malloc(sizeof(RingBuffer));
    if(!buf){
        return 0;
    }
    buf->buffer = (char*)malloc(size);
    if(!buf->buffer){
        free(buf->buffer);
        return 0;
    }
    buf->read = buf->write = 0;
    buf->size = size;
    buf->mode = mode;
    return buf;
}
void ring_buffer_free(RingBuffer* buffer){
    free(buffer->buffer);
    free(buffer);
}
int ring_buffer_write(RingBuffer* buffer,char* data,int size){
    int ret = 0;
    int full = ring_buffer_is_full(buffer);
    
    for(int i = 0;i <size;i++){
        if(full && buffer->mode == DROP){
            return ret;
        }
        buffer->buffer[buffer->write++] = data[i];
        ret ++;
        buffer->write %= buffer->size;
        if(full || (full = ring_buffer_is_full(buffer))){
            buffer->read = (buffer->write+1) % buffer->size;
        }    
    }
    return ret;
}
int ring_buffer_read(RingBuffer* buffer,char* out,int size){
    int ret = 0;
    for(int i = 0;ring_buffer_is_empty(buffer) == 0 && i<size;i++,buffer->read %= buffer->size){        
        out[i] = buffer->buffer[buffer->read++];
        ret ++;
    }
    return ret;
}
int ring_buffer_len(RingBuffer* buffer){
    int len = buffer->write - buffer->read;
    if(buffer->write >= buffer->read){
        return len;
    }
    return len + buffer->size;
}
int ring_buffer_is_full(RingBuffer* buffer){
    return ((buffer->write + 1) % buffer->size) == buffer->read;
}
int ring_buffer_is_empty(RingBuffer* buffer){
    return buffer->write == buffer->read;
}
int ring_buffer_clear(RingBuffer* buffer){
    buffer->write = buffer->read = 0;
}

void ring_buffer_dump(RingBuffer* buffer){
    debugf("mode:%d buffer:%p size:%d write:%d read:%d len:%d",
        buffer->mode,
        buffer->buffer,
        buffer->size,
        buffer->write,
        buffer->read,
        ring_buffer_len(buffer)
    );
}